# 【一】加密算法的分类
# 【1】对称加密
# 加密的秘钥和解密的秘钥是同一个
# 【2】非对称加密
# 加密的秘钥和解密的秘钥可以是不同的

# 【二】对称加密算法介绍
# （1）什么是对称加密
# ● 对称加密又称单密钥加密，整个加密过程中只使用一个密钥。
# ● 所谓对称加密就是使用一把密钥加密，使用同一把密钥解密。
# ● 对称加密由于加解和解密使用的是同一个密钥算法，故而在加解密的过程中速度比较快，适合于数据量比较大的加解密。
# （2）对称加密的优缺点
# ● 对称加密的主要有优点就是算法公开、计算量小、加密速度快、加密效率高；
# ● 但是它也存在强大的缺点，缺点就是密钥协商过程中，一旦 密钥 泄露，别人可以获取到密钥，这样也能对密文进行解密。
# ● 另外，每对用户每次使用对称加密算法时，都需要使用其他人不知道的独一密钥，这会使得收、发双方所拥有的钥匙数量巨大，密钥管理成为双方的负担。
# （3）常用的对称加密算法
# ● DES、3DES、AES、TDEA、Blowfish、RC2、RC4 和 RC5 等。

# 【三】DES加密算法
# ● DES 加密解密算法最初由美国 IBM 公司研究人员所设计发明，且为第一个公开的商用密码算法标准，自诞生以来便得到了 ISO 的一致认可。
# ● DES 是分组密码算法的典型代表，它的明文分组长度为 64bits，密钥长度为 64bits，其中包括有 8bits 的奇偶校验，因此有效密钥长度为 56bits。
# ● DES 加密解密算法使用的过程相同，且可以随时均都可以进行变动。
# ● 它们其中有极少数被认为是易破解的弱密钥，但是很容易抛开它们不使用，因此其自身安全性主要依赖于有效密钥。

# 【四】AES加密算法
# ● AES 加密算法为分组密码，分组长度为 128 位即 16 个字节，密匙长度有128、192 或 256 位，根据密匙 长 度的不同，加密的轮数也不同，本文采用长度为 128 位的密匙，加密轮数为 10 轮。
# ● AES 加密算法不仅编码紧凑、设计简单而且可抵抗多种类型的攻击，其基本结构包括 ４个部分。
# ● 这四个部分分别为字节替换、行位移、列混合和轮密匙加。


# 【五】AES加密算法在Python中的实现
# 【1】前提 必须安装第三方的库
# pip install pycryptodome

# 【2】AES的加密模式
# 两种加密模式 ECB ~ CBC
# 在前端看到AES加密一般就是这两种
# ECB 加密模式不需要偏移量  只需要原始数据 + 秘钥
# CBC 加密模式需要偏移量 需要原始数据 + 秘钥 + 偏移量

# 【3】AES中的参数介绍
from Crypto.Cipher import AES
import base64
from Crypto.Util.Padding import pad, unpad

# pad 填充数据到指定长度
# unpad 解析数据然后删减到指定长度

# 参数 key(bytes/bytearray/memoryview) : It must be 16 (*AES-128)*, 24 (*AES-192*) or 32 (*AES-256*) bytes long.
# 参数  mode (a ``MODE_*`` constant): 加密模式 AES.MODE_ECB / AES.MODE_CBC
# 参数  iv (bytes/bytearray/memoryview): it must be 16 bytes long for encryption / Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``

# 初始化 AES 对象 总结
#   秘钥必须为16字节或者16字节的倍数的字节型数据。
#   iv 偏移量 必须为16字节或者16字节的倍数的字节型数据。 (只限于指定的模式中)

# 待解密或加密的数据 明文必须为16字节或者16字节的倍数的字节型数据


# 【六】AES中的ECB模式
# 【1】加密逻辑
'''
# （1）创建一个 aes 的 ecb 模式的对象
key = "1234567891234567"  # 二进制的 key
cipher = AES.new(key=key.encode(), mode=AES.MODE_ECB)
# （2）获取到原始数据
original_data = "今天天气真好!"
# 给原始数据转为二进制数据
original_data_bytes = original_data.encode("utf8")
# （3）对原始的数据是由要求的 填充到指定的数据长度内
# 对base64编码后的数据进行加密
original_data_bytes = pad(original_data_bytes, block_size=AES.block_size)
# （4）将填充后的 base64 编码后的数据交给 ECB 加密
encrypted_data = cipher.encrypt(original_data_bytes)
# （5）提取出加密后的内容
# 发现加密后的二进制数据是无法通过 decode 解码 所以这时候就需要一个媒介 base64
# 将二进制数据转为 base64 编码后的字符串
last_data = base64.b64encode(encrypted_data).decode()
# bLLW7QIzRbJa3f97P3II4uKcw9V6JYUAWx74niessQo=
'''
# 【2】解密逻辑
'''
# （1）创建一个 aes 的 ecb 模式的对象
key = "1234567891234567"  # 二进制的 key
cipher = AES.new(key=key.encode(), mode=AES.MODE_ECB)
# （2）获取到原加密后的原始数据
original_data = "bLLW7QIzRbJa3f97P3II4uKcw9V6JYUAWx74niessQo="
# 给原始数据转为二进制数据
original_data_bytes = original_data.encode("utf8")
base64_decode = base64.b64decode(original_data_bytes)
# print(base64_decode) # b"l\xb2\xd6\xed\x023E\xb2Z\xdd\xff{?r\x08\xe2\xe2\x9c\xc3\xd5z%\x85\x00[\x1e\xf8\x9e'\xac\xb1\n"
# （3）对原始的数据是由要求的 填充到指定的数据长度内
# 对base64编码后的数据进行加密
# （4）将填充后的 base64 编码后的数据交给 ECB 解密
decrypted_data = cipher.decrypt(base64_decode)
# print(decrypted_data) # b'\xe4\xbb\x8a\xe5\xa4\xa9\xe5\xa4\xa9\xe6\xb0\x94\xe7\x9c\x9f\xe5\xa5\xbd!\r\r\r\r\r\r\r\r\r\r\r\r\r'
# （5）提取出解密后的内容
last_data = unpad(decrypted_data, block_size=AES.block_size).decode()
print(last_data)

'''
